package com.gemini.main.counter;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * com.gemini.main.counter.CounterTester
 *
 * @author zhanghailin
 */
public class CounterTester {

    private static final int THREAD_SIZE = 6;//add方法的并发线程数
    private static final int ADD_SIZE = 5000000;//测试规模
    private static final int KEYS_SIZE = 128 * 1024;

    public static void main(String[] args) throws InterruptedException {
        Counter[] counters = new Counter[]{new SynchronizedCounter(), new IncompleteCounter(), new ReadWriteLockCounter(), new CustomLockCounter(), new CompensationCounter()};
        String[] keys = new String[KEYS_SIZE];
        Random random = new Random();
        for (int i = 0; i < keys.length; i++) {
            keys[i] = String.valueOf(random.nextInt(KEYS_SIZE * 1024));
        }
        for (Counter counter : counters) {
            AtomicInteger totalLike = new AtomicInteger();
            AtomicInteger totalComment = new AtomicInteger();
            AtomicInteger savedTotalLike = new AtomicInteger();
            AtomicInteger savedTotalComment = new AtomicInteger();
            Counter.Saver saver = (key, like, comment) -> {
                savedTotalLike.addAndGet(like);//模拟被持久化到数据库，记录数量以便后续校验正确性
                savedTotalComment.addAndGet(comment);//同上
            };
            CountDownLatch latch = new CountDownLatch(THREAD_SIZE);
            long start = System.currentTimeMillis();
            for (int i = 0; i < THREAD_SIZE; i++) {
                new Thread(() -> {
                    Random r = new Random();
                    int like, comment;
                    for (int j = 0; j < ADD_SIZE; j++) {
                        like = 2;
                        comment = 4;
                        counter.add(keys[r.nextInt(KEYS_SIZE)], like, comment);
                        totalLike.addAndGet(like);
                        totalComment.addAndGet(comment);
                    }
                    latch.countDown();
                }).start();
            }
            Thread saveThread = new Thread(() -> {
                while (latch.getCount() != 0) {
                    try {
                        Thread.sleep(100);//模拟100毫秒执行一次持久化
                    } catch (InterruptedException e) {
                    }
                    counter.save(saver);
                }
                counter.save(saver);

            });
            saveThread.start();
            latch.await();
            System.out.println(counter.getClass().getSimpleName() + " cost:\t" + (System.currentTimeMillis() - start));
            saveThread.join();
            boolean error = savedTotalLike.get() != totalLike.get() || savedTotalComment.get() != totalComment.get();
            (error ? System.err : System.out).println("saved:\tlike=" + savedTotalLike.get() + "\tcomment=" + savedTotalComment.get());
            (error ? System.err : System.out).println("added:\tlike=" + totalLike.get() + "\tcomment=" + totalComment.get() + "\n");
        }
    }
}
